package step

import (
	"crypto/sha256"
	"github.com/wanchain/go-mpc/common"
	"github.com/wanchain/go-mpc/log"
	"github.com/wanchain/go-mpc/p2p/discover"
	mpcprotocol "github.com/wanchain/go-mpc/storeman/storemanmpc/protocol"
)

type MpcMessageGenerator interface {
	//initialize(*[]mpcprotocol.PeerInfo, mpcprotocol.MpcResultInterface) error
	initialize(int, mpcprotocol.MpcResultInterface) error
	calculateResult() error
	SetSchnorrMpcer(smcer mpcprotocol.SchnorrMPCer) error
	SetContextId(contextId uint64)
	GetContextId() uint64

	SetMpcContext(mpc MpcContextFunc)
	GetMpcContext() MpcContextFunc
}

type BaseMpcStep struct {
	BaseStep
	messages []MpcMessageGenerator
}

func CreateBaseMpcStep(totalNum int, messageNum int) *BaseMpcStep {
	return &BaseMpcStep{
		*CreateBaseStep(totalNum, -1),
		make([]MpcMessageGenerator, messageNum)}
}

func (mpcStep *BaseMpcStep) InitStep(result mpcprotocol.MpcResultInterface) error {
	mpcStep.BaseStep.InitStep(result)
	for _, message := range mpcStep.messages {
		err := message.initialize(mpcStep.totalNum, result)
		if err != nil {
			log.SyslogErr("BaseMpcStep::InitStep", " init msg fail. err", err.Error(), "ctx", mpcStep.GetMpcContextId())
			return err
		}
	}

	return nil
}

func (mpcStep *BaseMpcStep) GetMsgGens() []MpcMessageGenerator {
	return mpcStep.messages
}

func (mpcStep *BaseMpcStep) FinishStep() error {
	err := mpcStep.BaseStep.FinishStep()
	if err != nil {
		return err
	}

	for _, message := range mpcStep.messages {
		err := message.calculateResult()
		if err != nil {
			log.SyslogErr("BaseMpcStep::FinishStep", "BaseMpcStep, calculate msg result fail. err", err.Error(), "ctx", mpcStep.GetMpcContextId())
			return err
		}
	}

	return nil
}

func (mpcStep *BaseMpcStep) ShowNotArriveNodes(hash common.Hash, selfNodeId *discover.NodeID) {
	if len(mpcStep.notRecvPeers) != 0 {
		for peerId, _ := range mpcStep.notRecvPeers {
			if peerId != *selfNodeId {
				log.SyslogErr("ShowNotArriveNodes", "hash(signedData)", hash.String(), "Not received data from ", peerId.String(), "ctx", mpcStep.GetMpcContextId())
			}
		}
	}
}

func (mpcStep *BaseMpcStep) GetSignedDataHash(result mpcprotocol.MpcResultInterface) (error, common.Hash) {
	var retHash = common.Hash{}
	M, err := result.GetByteValue(mpcprotocol.MpcM)
	if err != nil {
		log.SyslogErr("GetSignedDataHash . err", err.Error(), "ctx", mpcStep.GetMpcContextId())
		return err, retHash
	}
	retHash = sha256.Sum256(M)
	return nil, retHash
}
